home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q1082.dms / q1082.adf / src.lzh / Fig / SaveIFF.c < prev    next >
C/C++ Source or Header  |  1991-07-18  |  9KB  |  486 lines

  1. #define MAKE_ID(a,b,c,d)    (((LONG)(a) << 24) + ((LONG)(b) << 16) + ((LONG)(c) << 8) + (LONG)(d))
  2. #define line_bytes(width)    (((width + 15) >> 4) << 1)
  3.  
  4. #define FORM MAKE_ID('F','O','R','M')
  5. #define ILBM MAKE_ID('I','L','B','M')
  6. #define BMHD MAKE_ID('B','M','H','D')
  7. #define CMAP MAKE_ID('C','M','A','P')
  8. #define BODY MAKE_ID('B','O','D','Y')
  9. #define CAMG MAKE_ID('C','A','M','G')
  10.  
  11. union bytes4
  12. {
  13.     char b4_name[4];
  14.     LONG b4_type;
  15. };
  16.  
  17. struct iff_chunk
  18. {
  19.     union bytes4    iff_type;
  20.     LONG        iff_length;
  21. };
  22.  
  23. struct form_chunk
  24. {
  25.     union bytes4    fc_type;
  26.     LONG        fc_length;
  27.     union bytes4    fc_subtype;
  28. };
  29.  
  30. struct BitMapHeader
  31. {
  32.     UWORD w, h;
  33.     UWORD x, y;
  34.     UBYTE nPlanes;
  35.     UBYTE masking;
  36.     UBYTE compression;
  37.     UBYTE pad1;
  38.     UWORD transparentColor;
  39.     UBYTE xAspect, yAspect;
  40.     WORD pageWidth, pageHeight;
  41. };
  42.  
  43. #define DUMP    0
  44. #define RUN    1
  45.  
  46. #define MINRUN 3
  47. #define MAXRUN 128
  48. #define MAXDAT 128
  49.  
  50. /* pack_row - pass source line pointer, length of line, and file.
  51.    Returns # of bytes after compression.  Returns 0 on write error.
  52.    Pass file = NULL to just find out length,
  53.    otherwise will write compressed row to file. */
  54.  
  55. LONG
  56. pack_row(file,source,size)
  57. FILE *file;
  58. char *source;
  59. LONG size;
  60. {
  61.     char c,lastc = '\0';
  62.     LONG mode = DUMP;
  63.     LONG nbuf = 0;        /* number of chars in buffer */
  64.     LONG rstart = 0;    /* buffer index current run starts */
  65.     LONG putsize;
  66.     char buf[MAXDAT*3/2];    /* I think MAXDAT+1 would suffice */
  67.  
  68.     putsize = 0;
  69.     buf[0] = lastc = *source++;/* so have valid lastc */
  70.     nbuf = 1;
  71.     size--;            /* since one byte eaten. */
  72.  
  73.  
  74.     for(; size ; --size)
  75.     {
  76.         buf[nbuf++] = c = *source++;
  77.  
  78.         switch(mode)
  79.         {
  80.             case DUMP:    /* If the buffer is full, write the length byte, then the data */
  81.                     if(nbuf > MAXDAT)
  82.                     {
  83.                         if(file != NULL)
  84.                         {
  85.                             if(fputc(nbuf-2,file) == EOF)
  86.                                 return(0);
  87.  
  88.                             if(fwrite(buf,nbuf-1,1,file) == EOF)
  89.                                 return(0);
  90.                         }
  91.  
  92.                         putsize += nbuf;
  93.                         buf[0] = c;
  94.                         nbuf = 1;
  95.                         rstart = 0;
  96.                         break;
  97.                     }
  98.  
  99.                     if(c == lastc)
  100.                     {
  101.                         if(nbuf - rstart >= MINRUN)
  102.                         {
  103.                             if(rstart > 0)
  104.                             {
  105.                                 if(file != NULL)
  106.                                 {
  107.                                     if(fputc(rstart-1,file) == EOF)
  108.                                         return(0);
  109.  
  110.                                     if(fwrite(buf,rstart,1,file) == EOF)
  111.                                         return(0);
  112.                                 }
  113.  
  114.                                 putsize += rstart+1;
  115.                             }
  116.  
  117.                             mode = RUN;
  118.                         }
  119.                         else
  120.                             if(rstart == 0)
  121.                                 mode = RUN;
  122.  
  123.                             /* no dump in progress, so can't lose by making
  124.                                these 2 a run. */
  125.                     }
  126.                     else
  127.                         rstart = nbuf - 1;/* first of run */
  128.  
  129.                     break;
  130.  
  131.             case RUN:    if((c != lastc) ||(nbuf - rstart > MAXRUN))
  132.                     {
  133.                         /* output run */
  134.                         if(file != NULL)
  135.                         {
  136.                             if(fputc(-(nbuf - rstart - 2),file) == EOF)
  137.                                 return(0);
  138.  
  139.                             if(fputc(lastc,file) == EOF)
  140.                                 return(0);
  141.                         }
  142.  
  143.                         putsize += 2;
  144.  
  145.                         buf[0] = c;
  146.                         nbuf = 1;
  147.                         rstart = 0;
  148.                         mode = DUMP;
  149.                     }
  150.  
  151.                     break;
  152.         }
  153.  
  154.         lastc = c;
  155.     }
  156.  
  157.     switch(mode)
  158.     {
  159.         case DUMP:    if(file != NULL)
  160.                 {
  161.                     if(fputc(nbuf-1,file) == EOF)
  162.                         return(0);
  163.  
  164.                     if(fwrite(buf,nbuf,1,file) == EOF)
  165.                         return(0);
  166.                 }
  167.  
  168.                 putsize += nbuf+1;
  169.                 break;
  170.  
  171.         case RUN:    if(file != NULL)
  172.                 {
  173.                     if(fputc(-(nbuf - rstart - 1),file) == EOF)
  174.                         return(0);
  175.  
  176.                     if(fputc(lastc,file) == EOF)
  177.                         return(0);
  178.                 }
  179.  
  180.                 putsize += 2;
  181.                 break;
  182.     }
  183.  
  184.     return(putsize);
  185. }
  186.  
  187. LONG
  188. pack_bitmap(file,bm,height)
  189. FILE *file;
  190. struct BitMap *bm;
  191. LONG height;
  192. {
  193.     LONG i,j;
  194.     LONG row_length,compressed_length;
  195.     LONG plane_offset;
  196.  
  197.     compressed_length = 0;
  198.     plane_offset = 0;
  199.  
  200.     for(i = 0 ; i < height ; i++)
  201.     {
  202.         for(j = 0 ; j < bm -> Depth ; j++)
  203.         {
  204.             if((row_length = pack_row(file,bm -> Planes[j] + plane_offset,bm -> BytesPerRow)) == 0)
  205.                 return(0);
  206.  
  207.             compressed_length += row_length;
  208.         }
  209.  
  210.         plane_offset += bm -> BytesPerRow;
  211.     }
  212.  
  213.     if(compressed_length & 1)  /*check to see odd length */
  214.     {
  215.         if(file != NULL)        /*pad with 0 to make it even */
  216.             if(fputc(0,file) == EOF)
  217.                 return(0);
  218.  
  219.         compressed_length++;
  220.     }
  221.  
  222.     return(compressed_length);
  223. }
  224.  
  225. LONG
  226. write_iff(name,colors,bits,xoff,yoff,width,height,compressed,pagewidth,pageheight,viewmodes)
  227. char *name;
  228. unsigned char *colors;
  229. register struct BitMap *bits;
  230. LONG xoff,yoff;
  231. LONG width,height,compressed;
  232. LONG pagewidth,pageheight;
  233. LONG viewmodes;
  234. {
  235.     FILE *file;
  236.     struct form_chunk chunk;
  237.     struct iff_chunk ichunk;
  238.     struct BitMapHeader header;
  239.     LONG bits_size,numcols = 32,row_offset;
  240.     register LONG i,j;
  241.  
  242.     if(bits)
  243.     {
  244.         if((numcols = 1 << bits -> Depth) == 64)
  245.             numcols = 32;
  246.  
  247.         if(viewmodes & HAM)
  248.             numcols = 16;
  249.     }
  250.  
  251.     if(!(file = fopen(name,"w")))
  252.         return(FALSE);
  253.  
  254.     /* say its a FORM ILBM */
  255.  
  256.     chunk . fc_type       . b4_type    = FORM;
  257.     chunk . fc_subtype . b4_type    = ILBM;
  258.     chunk . fc_length        = sizeof(struct form_chunk) + 3 * sizeof(struct iff_chunk) + numcols * 3 + sizeof(struct BitMapHeader) + sizeof(LONG);
  259.  
  260.     if(bits)
  261.     {
  262.         if(compressed)
  263.         {
  264.             if((bits_size = pack_bitmap(NULL,bits,height)) == 0)
  265.             {
  266.                 fclose(file);
  267.                 return(FALSE);
  268.             }
  269.         }
  270.         else
  271.             bits_size = bits -> BytesPerRow * bits -> Rows * bits -> Depth;
  272.  
  273.         chunk . fc_length += bits_size;
  274.     }
  275.     else
  276.         chunk . fc_length -= sizeof(struct iff_chunk);
  277.  
  278.     if(fwrite(&chunk,sizeof(chunk),1,file) == EOF)
  279.     {
  280.         fclose(file);
  281.         return(FALSE);
  282.     }
  283.  
  284.     /* here comes a BitMapHeader */
  285.  
  286.     ichunk . iff_type . b4_type    = BMHD;
  287.     ichunk . iff_length        = sizeof(header);
  288.  
  289.     if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
  290.     {
  291.         fclose(file);
  292.         return(FALSE);
  293.     }
  294.  
  295.     /* initialize the BitMapHeader to normal values */
  296.  
  297.     header . masking        = 0;
  298.     header . pad1            = 0;
  299.     header . transparentColor    = 0;
  300.  
  301.     if(compressed)
  302.         header . compression = 1;
  303.     else
  304.         header . compression = 0;
  305.  
  306.     header . pageWidth    = pagewidth;
  307.     header . pageHeight    = pageheight;
  308.     header . yAspect    = 11;
  309.  
  310.     viewmodes &= ~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO);
  311.  
  312.     if((viewmodes & HIRES) && (viewmodes & LACE))
  313.         header . xAspect = 10;
  314.  
  315.     if(!(viewmodes & HIRES) && (viewmodes & LACE))
  316.         header . xAspect = 20;
  317.  
  318.     if((viewmodes & HIRES) && !(viewmodes & LACE))
  319.         header . xAspect = 5;
  320.  
  321.     if(!(viewmodes & HIRES) && !(viewmodes & LACE))
  322.         header . xAspect = 10;
  323.  
  324.     /* if it's not just a color map give the dimensions of rasters */
  325.  
  326.     if(bits)
  327.     {
  328.         header . w    = width;
  329.         header . h    = height;
  330.         header . nPlanes= bits -> Depth;
  331.         header . x    = xoff;
  332.         header . y    = yoff;
  333.     }
  334.  
  335.     if(fwrite(&header,sizeof(header),1,file) == EOF)
  336.     {
  337.         fclose(file);
  338.         return(FALSE);
  339.     }
  340.  
  341.     /* squirt out the color map */
  342.  
  343.     ichunk . iff_type . b4_type    = CMAP;
  344.     ichunk . iff_length        = numcols * 3;
  345.  
  346.     if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
  347.     {
  348.         fclose(file);
  349.         return(FALSE);
  350.     }
  351.  
  352.     if(fwrite(colors,3 * numcols,1,file) == EOF)
  353.     {
  354.         fclose(file);
  355.         return(FALSE);
  356.     }
  357.  
  358.     /* send it a CAMG chunk */
  359.  
  360.     ichunk . iff_type . b4_type    = CAMG;
  361.     ichunk . iff_length        = sizeof(LONG);
  362.  
  363.     if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
  364.     {
  365.         fclose(file);
  366.         return(FALSE);
  367.     }
  368.  
  369.     if(fwrite(&viewmodes,sizeof(LONG),1,file) == EOF)
  370.     {
  371.         fclose(file);
  372.         return(FALSE);
  373.     }
  374.  
  375.     /* if they be bits then squirt out the bits */
  376.  
  377.     if(bits)
  378.     {
  379.         ichunk . iff_type . b4_type    = BODY;
  380.         ichunk . iff_length        = bits_size;
  381.  
  382.         if(fwrite(&ichunk,sizeof(ichunk),1,file) == EOF)
  383.         {
  384.             fclose(file);
  385.             return(FALSE);
  386.         }
  387.  
  388.         if(compressed)
  389.         {
  390.             if(pack_bitmap(file,bits,height) == 0)
  391.             {
  392.                 fclose(file);
  393.                 return(FALSE);
  394.             }
  395.         }
  396.         else
  397.         {
  398.             i = height;
  399.             row_offset = 0;
  400.  
  401.             while(--i >= 0)
  402.             {
  403.                 for(j = 0 ; j < bits -> Depth ; j++)
  404.                 {
  405.                     if(fwrite(bits -> Planes[j] + row_offset,height,1,file) == EOF)
  406.                     {
  407.                         fclose(file);
  408.                         return(FALSE);
  409.                     }
  410.  
  411.                     row_offset += bits -> BytesPerRow;
  412.                 }
  413.             }
  414.         }
  415.     }
  416.  
  417.     fclose(file);
  418.     return(TRUE);
  419. }
  420.  
  421. LONG
  422. SaveRPort(RPort,VPort,LeftEdge,TopEdge,Width,Height,ParentWidth,ParentHeight,Cookie,Name)
  423. struct RastPort *RPort;
  424. struct ViewPort *VPort;
  425. LONG LeftEdge,TopEdge,Width,Height,ParentWidth,ParentHeight,Cookie;
  426. STRPTR Name;
  427. {
  428.     char ColTable[32 * 3];
  429.     struct BitMap DstMap,*SMap = RPort -> BitMap;
  430.     LONG IFF_Result;
  431.     LONG i,Modes;
  432.     LONG r,g,b;
  433.  
  434.     extern struct GfxBase *GfxBase;
  435.  
  436.     if(!RPort || !VPort || !Name || Width < 1 || Height < 1)
  437.         return(FALSE);
  438.  
  439.     if(LeftEdge || TopEdge || Cookie)
  440.     {
  441.         Cookie = TRUE;
  442.  
  443.         InitBitMap(&DstMap,SMap -> Depth,Width,Height);
  444.  
  445.         for(i = 0 ; i < SMap -> Depth ; i++)
  446.         {
  447.             if(!(DstMap . Planes[i] = (PLANEPTR)AllocMem(line_bytes(Width) * Height,MEMF_CHIP | MEMF_CLEAR)))
  448.             {
  449.                 IFF_Result = FALSE;
  450.                 goto Stop;
  451.             }
  452.         }
  453.  
  454.         BltBitMap(SMap,LeftEdge,TopEdge,&DstMap,0,0,Width,Height,0xC0,0xFF);
  455.  
  456.         SMap = &DstMap;
  457.     }
  458.  
  459.     if(GfxBase -> LibNode . lib_Version >= 36)
  460.         Modes = GetVPModeID(VPort);
  461.     else
  462.         Modes = VPort -> Modes;
  463.  
  464.     for(i = 0 ; i < 32 ; i++)
  465.     {
  466.         UWORD TmpCol = GetRGB4(VPort -> ColorMap,i);
  467.  
  468.         r = (TmpCol >> 8) & 0xF;
  469.         g = (TmpCol >> 4) & 0xF;
  470.         b = (TmpCol     ) & 0xF;
  471.  
  472.         ColTable[i * 3 + 0] = r << 4;
  473.         ColTable[i * 3 + 1] = g << 4;
  474.         ColTable[i * 3 + 2] = b << 4;
  475.     }
  476.  
  477.     IFF_Result = write_iff(Name,ColTable,SMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,Modes);
  478.  
  479. Stop:    if(Cookie)
  480.         for(i = 0 ; i < DstMap . Depth ; i++)
  481.             if(DstMap . Planes[i])
  482.                 FreeMem(DstMap . Planes[i],line_bytes(Width) * Height);
  483.  
  484.     return(IFF_Result);
  485. }
  486.